package com.ruoyi.framework.app.service.impl;

import com.ruoyi.common.core.domain.AjaxResults;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.SnowFlakeUtil;
import com.ruoyi.framework.app.service.IKUsersFraneworkService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.qsng.domain.KUsers;
import com.ruoyi.qsng.domain.KUsersInformation;
import com.ruoyi.qsng.dto.AppRowData;
import com.ruoyi.qsng.dto.Authcode2Session;
import com.ruoyi.qsng.dto.UserGrantDto;
import com.ruoyi.qsng.mapper.KUsersInformationMapper;
import com.ruoyi.qsng.mapper.KUsersMapper;
import com.ruoyi.qsng.utils.AESForWeixinGetPhoneNumber;
import com.ruoyi.qsng.utils.WeixinPhoneDecryptInfo;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.util.*;


/**
 * 用户信息Service业务层处理
 * 
 * @author kanglou
 * @date 2023-06-07
 */
@Slf4j
@Service
public class KUsersFraneworkServiceImpl implements IKUsersFraneworkService
{
    public static final String APP_ID = "wx2c8c2c1fc2b4d594";
    public static final String APP_SECRET = "8662e3ef59e0384cd6edc4d34d32353a";


    @Autowired
    private KUsersMapper kUsersMapper;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private RestTemplate restTemplate;


    @Autowired
    private TokenService tokenService;

    @Autowired
    private KUsersInformationMapper kUsersInformationMapper;



    @Override
    public KUsers callBack(JSONObject jsonObject,String openid) {
        //从redis中获取用户的认证信息
        redisCache.deleteObject(openid);
        //openid查询用户
        KUsers user = kUsersMapper.selectByOpenid(openid);
        if (Objects.isNull(user)) {// 新增
            log.info("微信登录2：------------------>user为空");
            //说明用户第一次登录，数据库中创建用户
            KUsers users =new KUsers();
            if(jsonObject!=null) {

                JSONObject rawDataJson = JSONObject.fromObject(jsonObject);
                AppRowData appRowData = (AppRowData) JSONObject.toBean(rawDataJson, AppRowData.class);
                users.setOpenId(openid);
//                users.setUserName(String.valueOf(1111));
//                user.setPassword(SecurityUtils.encryptPassword("123456"));
                String id =SnowFlakeUtil.getNextId();
                users.setId(id);
                users.setCreateTime(new Date());
                kUsersMapper.insertKUsers(users);

                KUsersInformation kUsersInformation =new KUsersInformation();
                kUsersInformation.setOpenid(openid);
                kUsersInformation.setNickName(appRowData.getNickname());
                kUsersInformation.setUserName(appRowData.getNickname());
                kUsersInformation.setAvatar(appRowData.getHeadimgurl());
                String id1 =SnowFlakeUtil.getNextId();
                kUsersInformation.setId(id1);
                kUsersInformationMapper.insertKUsersInformation(kUsersInformation);

                // 生成token，并存入到redis和数据库中
                String token = getToken(users);
                log.info("生成的token为：{}", token);
                users.setToken(token);
                users.setAvatarUrl(appRowData.getHeadimgurl());
                users.setNickName(appRowData.getNickname());
                log.info("微信登录4：------------------>登录成功{}");
            }
            return  users;

        }
        // 生成token，并存入到redis和数据库中
        String token = getToken(user);
        log.info("生成的token为：{}", token);
        user.setToken(token);
        log.info("微信登录4：------------------>登录成功{}");
        return  user;
    }

    @Override
    public AjaxResults<KUsers> devLogin(String openid, String telephone) {
        AppRowData appRowData = new AppRowData();
        appRowData.setNickname("后台开发人员");
        //手机号查询用户
        KUsers user = kUsersMapper.selectByTelephone(telephone);
        if (Objects.isNull(user)) {
            //说明用户第一次登录，数据库中创建用户
            KUsers firstLoginUser = createUserByAppRowData(openid, appRowData, telephone);

            kUsersMapper.insertKUsers(firstLoginUser);
            user = firstLoginUser;
        }
        // 生成token，并存入到redis和数据库中
        String token = getToken(user);
        log.info("生成的token为：{}", token);
        user.setToken(token);
        return AjaxResults.success("用户登录成功", token);
    }

    @Override
    public AjaxResults<String> apploginOut(HttpServletRequest request) {
        LoginUser loginUser = tokenService.getLoginUser(request);
        if (Objects.nonNull(loginUser)) {
            tokenService.delLoginUser(loginUser.getToken());
        }
        return AjaxResults.success("退出成功");
    }

    @Override
    public AjaxResults<KUsers> appChangePassword(String oldPassword, String newPassword, String newPasswordConfirm) {
        Long id = SecurityUtils.getLoginUser().getUser().getUserId();
        KUsers user = kUsersMapper.selectKUsersById(String.valueOf(id));
        if (Objects.isNull(user)) {
            log.error("用户不存在， id: {}", id);
            return AjaxResults.error("用户不存在");
        }
        //先判断两次新密码是否一致
        if (!Objects.equals(newPassword, newPasswordConfirm)) {
            return AjaxResults.error("您两次输入的新密码不一致，请重新输入!");
        }
        //判断原密码是否正确
        //校验密码是否一致
        if (!SecurityUtils.matchesPassword(oldPassword, user.getPassword())) {
            return AjaxResults.error("原密码输入错误!");
        }
        user.setPassword(SecurityUtils.encryptPassword(newPassword));
        user.setUpdateTime(new Date());
        kUsersMapper.updateKUsers(user);
        return AjaxResults.success(user);
    }

    @Override
    public AjaxResults<KUsers> appPhoneLogin(String phone, String password) {
        KUsers user = kUsersMapper.selectByTelephone(phone);
        if (Objects.isNull(user)) {
            return AjaxResults.error("用户不存在，请联系管理员添加");
        }
        //校验密码是否一致
        if (!SecurityUtils.matchesPassword(password, user.getPassword())) {
            return AjaxResults.error("用户名或者密码错误");
        }

        String token = getToken(user);
        user.setToken(token);

        KUsersInformation kUsersInformation =kUsersInformationMapper.selectKUsersInformationByPhone(user.getUserName());
        user.setName(kUsersInformation.getUserName());
        user.setAvatarUrl(kUsersInformation.getAvatar());

        return  AjaxResults.success("用户登录成功", user);
    }

    @Override
    @Transactional
    public AjaxResults<KUsers> appLogin(String openid, String rawData, String encryptedData, String iv ){

        log.info("微信登录1：------------------>companyId {}");

        //从redis中获取用户的认证信息
        Authcode2Session authResultFromWeixin = redisCache.getCacheObject(openid);
        redisCache.deleteObject(openid);
        //openid查询用户
        KUsers user = kUsersMapper.selectByOpenid(openid);
        String telphone = null;
        //解密手机号
        if (Objects.isNull(user)) {
            //需要解密手机号
            if (StringUtils.isEmpty(encryptedData) || StringUtils.isEmpty(iv)) {
                log.error("encryptedData或者iv传值为空, 接口异常");
                return AjaxResults.error("手机号解密失败！！");
            }
            AESForWeixinGetPhoneNumber aes = new AESForWeixinGetPhoneNumber(encryptedData, authResultFromWeixin.getSession_key(), iv);
            WeixinPhoneDecryptInfo phoneDecryptInfo = aes.decrypt();
            if (null == phoneDecryptInfo) {
                log.error("手机号解密失败！！！");
                return AjaxResults.error("手机号解密失败！！");
            }
            log.info("解密后的手机号信息：{}", phoneDecryptInfo.toString());
            telphone = phoneDecryptInfo.getPhoneNumber();
            //如果用户存在，但是对应微信手机号被人工添加到了后台，则按手机号查询
            user = kUsersMapper.selectByTelephone(telphone);
        } else {
            //不需要解密手机号
            telphone = user.getUserName();
        }

        if (Objects.isNull(user)) {// 新增
            log.info("微信登录2：------------------>user为空");
            //说明用户第一次登录，数据库中创建用户
            KUsers users =new KUsers();
            if(rawData!=null) {
                JSONObject rawDataJson = JSONObject.fromObject(rawData);
                AppRowData appRowData = (AppRowData) JSONObject.toBean(rawDataJson, AppRowData.class);
                KUsers firstLoginUser = createUserByAppRowData(openid, appRowData, telphone);
                firstLoginUser.setUpdateTime(new Date());
                firstLoginUser.setUserName(telphone);
                String id =SnowFlakeUtil.getNextId();
                 firstLoginUser.setId(id);
                firstLoginUser.setOpenId(openid);
                firstLoginUser.setPassword(SecurityUtils.encryptPassword("123456"));
                kUsersMapper.insertKUsers(firstLoginUser);
//                //报名信息
//                KUsersInformation kUsersInformation = new KUsersInformation();
//                kUsersInformation.setPhone(telphone);
//                kUsersInformation.setAvatar(appRowData.getAvatarUrl());
//                kUsersInformation.setId(SnowFlakeUtil.getNextId());
//                kUsersInformation.setUserName(appRowData.getNickName());
//                kUsersInformationMapper.insertKUsersInformation(kUsersInformation);


                users.setId(id);
//                users.setName(appRowData.getNickName());
//                users.setAvatarUrl(appRowData.getAvatarUrl());
                // 生成token，并存入到redis和数据库中
                String token = getToken(users);
                log.info("生成的token为：{}", token);
                users.setToken(token);
                log.info("微信登录4：------------------>登录成功{}");
            }
            return  AjaxResults.success("用户登录成功", users);

        } else {
            user.setOpenId(openid);
            user.setUpdateTime(new Date());
            KUsersInformation kUsersInformation =kUsersInformationMapper.selectKUsersInformationByPhone(user.getUserName());
            user.setName(kUsersInformation.getUserName());
            user.setAvatarUrl(kUsersInformation.getAvatar());
            //如果没有密码，则添加默认密码 123456
            if (StringUtils.isEmpty(user.getPassword())) {
                user.setPassword(SecurityUtils.encryptPassword("123456"));
            }
            kUsersMapper.updateKUsers(user);
        }
        // 生成token，并存入到redis和数据库中
        String token = getToken(user);
        log.info("生成的token为：{}", token);
        user.setToken(token);
        log.info("微信登录4：------------------>登录成功{}");
        return  AjaxResults.success("用户登录成功", user);
    }

    public String getToken(KUsers user) {
        LoginUser loginUser = new LoginUser(createManager(user), new HashSet<>());
        // 生成token
        return tokenService.createToken(loginUser);
    }

    private SysUser createManager(KUsers user) {
        SysUser sysUser = new SysUser();
        sysUser.setUserName(user.getUserName());
        sysUser.setUserId(Long.valueOf(user.getId()));
        sysUser.setRoles(new ArrayList<>());
        return sysUser;
    }

    private KUsers createUserByAppRowData(String openid, AppRowData appRowData, String mobilePhone) {
        KUsers user = new KUsers();
        user.setUserName(mobilePhone);
        user.setCreateTime( new Date());
        String id =SnowFlakeUtil.getNextId();
        user.setId(id);
        //第一次登录，创建默认密码 123456
        user.setPassword(SecurityUtils.encryptPassword("123456"));

        //报名信息
        KUsersInformation kUsersInformation = new KUsersInformation();
        kUsersInformation.setPhone(mobilePhone);
//        kUsersInformation.setAvatar(appRowData.getAvatarUrl());
        kUsersInformation.setId(SnowFlakeUtil.getNextId());
//        kUsersInformation.setUserName(appRowData.getNickName());
        kUsersInformationMapper.insertKUsersInformation(kUsersInformation);
        return user;
    }

    /**
     * 调用微信认证
     *
     * @param code
     * @return
     */
    private Authcode2Session authFromWeixin(String code) {
        String appId = APP_ID;
        String appSecret = APP_SECRET;

        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appId +
                "&secret=" + appSecret + "&js_code=" + code + "&grant_type=authorization_code";
        Authcode2Session authResultFromWeixin = null;
        final int tryTimes = 3;
        for (int i = 0; i < tryTimes; i++) {
            String resultStr = restTemplate.getForObject(url, String.class);
            JSONObject jsonobject = JSONObject.fromObject(resultStr);
            authResultFromWeixin = (Authcode2Session) JSONObject.toBean(jsonobject, Authcode2Session.class);
            if (0 == authResultFromWeixin.getErrcode()) {
                break;
            }
        }
        return authResultFromWeixin;
    }

    @Override
    @Transactional(readOnly = true)
    public AjaxResults<UserGrantDto> isNeedGrantPhone(String code) {
        //微信认证
        Authcode2Session authResultFromWeixin = this.authFromWeixin(code);
        if (null == authResultFromWeixin || authResultFromWeixin.getErrcode() != 0) {
            log.error("微信认证失败！！！");
            log.info(authResultFromWeixin.toString());
            return AjaxResults.error("微信认证失败！！");
        }
        //成功后将认证信息存入redis
        redisCache.setCacheObject(authResultFromWeixin.getOpenid(), authResultFromWeixin);

        //请求成功
        String openid = authResultFromWeixin.getOpenid();
        KUsers user = kUsersMapper.selectByOpenid(openid);

        //如果用户不存在，或者微信手机号为空，则需要授权获取手机号
        boolean isNeedGrantPhone = true;
        //如果用户存在且微信手机号存在，则不需要授权获取手机号
        if (Objects.nonNull(user) && StringUtils.isNotEmpty(user.getUserName())) {
            isNeedGrantPhone = false;
        }
        UserGrantDto userGrantDto = new UserGrantDto(openid, isNeedGrantPhone);
        return AjaxResults.success(userGrantDto);
    }

    /**
     * 查询用户信息
     * 
     * @param id 用户信息主键
     * @return 用户信息
     */
    @Override
    public KUsers selectKUsersById(String id)
    {
        return kUsersMapper.selectKUsersById(id);
    }

    /**
     * 查询用户信息列表
     * 
     * @param kUsers 用户信息
     * @return 用户信息
     */
    @Override
    public List<KUsers> selectKUsersList(KUsers kUsers)
    {
        return kUsersMapper.selectKUsersList(kUsers);
    }

    /**
     * 新增用户信息
     * 
     * @param kUsers 用户信息
     * @return 结果
     */
    @Override
    public int insertKUsers(KUsers kUsers)
    {
        kUsers.setId(SnowFlakeUtil.getNextId());
        kUsers.setCreateTime(DateUtils.getNowDate());
        return kUsersMapper.insertKUsers(kUsers);
    }

    /**
     * 修改用户信息
     * 
     * @param kUsers 用户信息
     * @return 结果
     */
    @Override
    public int updateKUsers(KUsers kUsers)
    {
        kUsers.setUpdateTime(DateUtils.getNowDate());
        return kUsersMapper.updateKUsers(kUsers);
    }

    /**
     * 批量删除用户信息
     * 
     * @param ids 需要删除的用户信息主键
     * @return 结果
     */
    @Override
    public int deleteKUsersByIds(String[] ids)
    {
        return kUsersMapper.deleteKUsersByIds(ids);
    }

    /**
     * 删除用户信息信息
     * 
     * @param id 用户信息主键
     * @return 结果
     */
    @Override
    public int deleteKUsersById(String id)
    {
        return kUsersMapper.deleteKUsersById(id);
    }
}
